<template>
  <div class="x6-connector-wrapper">
    <!-- 线条类型选择器 -->
    <div class="line-type-selector">
      <div class="line-type-tabs">
        <div 
          v-for="lineType in lineTypes" 
          :key="lineType.id"
          :class="[
            'line-type-tab',
            { active: selectedLineType && selectedLineType.id === lineType.id },
          ]"
          @click="selectLineType(lineType)"
          :title="lineType.description"
        >
          <span class="line-type-icon">{{ lineType.icon }}</span>
          <span class="line-type-name">{{ lineType.name }}</span>
        </div>
      </div>
    </div>
    
    <div class="x6-container" ref="container"></div>
  </div>
</template>

<script>
import { Graph } from "@antv/x6";
import { Dnd } from "@antv/x6-plugin-dnd";
import { Snapline } from "@antv/x6-plugin-snapline";
import { IntersectionCalculator } from "../utils/intersectionCalculator";
import { PositionCalculator } from "../utils/positionCalculator";

export default {
  name: "X6Connector",
  data() {
    return {
      graph: null,
      dnd: null,
      tempPorts: new Set(),

      // 精准连线状态管理
      dragState: {
        isDragging: false, // 是否正在拖拽连线
        sourceNode: null, // 源节点
        sourcePort: null, // 源连接桩
        tempEdge: null, // 临时连线
        currentTarget: null, // 当前悬停的目标节点
      },

      // 目标节点高亮状态管理
      currentHoverNode: null, // 当前悬停的目标节点
      
      // 全局鼠标位置追踪
      lastMousePosition: { x: 0, y: 0 }, // 最后一次记录的鼠标位置

      // 线条类型选择器
      lineTypes: [
        {
          id: "polyline",
          name: "折线",
          icon: "⟲",
          description: "自动折线，智能避障",
          style: {
            stroke: "#faad14",
            strokeWidth: 2,
          },
          router: "manhattan",
          connector: "rounded",
          sourceMarker: null,
          targetMarker: {
            name: "block",
            width: 10,
            height: 6,
          },
        },
        {
          id: "basic",
          name: "直线",
          icon: "→",
          description: "基础直线箭头，适用于一般关系",
          style: {
            stroke: "#666",
            strokeWidth: 2,
          },
          router: "normal",
          connector: "normal",
          sourceMarker: null,
          targetMarker: {
            name: "block",
            width: 12,
            height: 8,
          },
        },
        {
          id: "curved",
          name: "曲线",
          icon: "↷",
          description: "平滑曲线箭头，适用于柔和连接",
          style: {
            stroke: "#1890ff",
            strokeWidth: 2,
          },
          router: "normal",
          connector: "smooth",
          sourceMarker: null,
          targetMarker: {
            name: "classic",
            size: 8,
          },
        },

        {
          id: "dashed",
          name: "虚线",
          icon: "⟶",
          description: "虚线箭头，适用于临时或条件关系",
          style: {
            stroke: "#52c41a",
            strokeWidth: 2,
            strokeDasharray: "8 4",
          },
          router: "normal",
          connector: "normal",
          sourceMarker: null,
          targetMarker: {
            name: "classic",
            size: 8,
          },
        },
      ],
      selectedLineType: null, // 当前选中的线条类型
      
      // 步骤6: 连线重连状态管理
      selectedEdge: null,
      edgeEndpoints: [],
      isDraggingEndpoint: false,
      draggedEndpoint: null,
      dragPreviewLine: null,
      previewEndpointMarker: null,
      updateScheduled: false,
      
      // 初次连线边框吸附状态
      pendingAttachmentPoint: null,
      shouldApplyAttachment: false
    };
  },
  mounted() {
    this.initGraph();
    this.initNodes();
    this.initEvents();
    this.setupGlobalMouseTracking();
    this.initLineTypeSelector();
    this.initEdgeSelectionEvents();
  },
  methods: {
    initGraph() {
      // 保存 Vue 组件实例的引用，用于回调函数中访问
      const self = this;
      
      this.graph = new Graph({
        container: this.$refs.container,
        width: 800,
        height: 600,
        grid: {
          size: 20,
          visible: true,
        },
        background: {
          color: "#f8f9fa",
        },
        interacting: {
          edgeLabelMovable: true,
        },
        // 禁用默认的选中和悬停样式
        selecting: {
          enabled: true,
          showNodeSelectionBox: false, // 禁用节点选中框
        },
        highlighting: {
          magnetAvailable: {
            name: "stroke",
            args: {
              attrs: {
                stroke: "transparent", // 隐藏连接桩高亮边框
                "stroke-width": 0,
              },
            },
          },
          magnetAdsorbed: {
            name: "stroke",
            args: {
              attrs: {
                stroke: "transparent", // 隐藏连接桩吸附边框
                "stroke-width": 0,
              },
            },
          },
        },
        connecting: {
          // 拖拽时使用直线，连接后使用智能路由
          router: "normal", // 拖拽时使用直线路由
          connector: "normal", // 拖拽时使用直线连接器
          anchor: "center",
          connectionPoint: "anchor",
          allowBlank: false,
          allowLoop: false,
          allowNode: true, // 允许连接到节点
          allowEdge: false,
          allowPort: true, // 允许连接到端口
          allowMulti: true,
          highlight: false, // 禁用默认高亮，我们自己实现
          snap: {
            radius: 20,
          },

          // 自定义连接点计算
          createEdge: () => {
            // 创建临时连线时应用我们的样式
            const lineConfig = self.getCurrentLineStyle();
            return self.graph.createEdge({
              router: lineConfig.router,
              connector: lineConfig.connector,
              attrs: {
                line: {
                  ...lineConfig.style,
                  targetMarker: lineConfig.targetMarker,
                  sourceMarker: lineConfig.sourceMarker,
                },
              },
            });
          },

          // 端口拖拽验证 - 当从端口开始拖拽时触发
          validateMagnet: ({ cell, magnet }) => {
            // 记录拖拽状态
            self.dragState.isDragging = true;
            self.dragState.sourceNode = cell;
            self.dragState.sourcePort = magnet
              ? magnet.getAttribute("port")
              : null;

            return true; // 允许从端口开始拖拽
          },
          
          // 连接验证 - 当尝试建立连接时触发
          validateConnection: ({
            sourceView,
            targetView,
          }) => {
            // 精准连线模式下阻止所有默认连接
            if (self.dragState.isDragging) {
              return false;
            }

            // 非精准连线模式的基本验证逻辑
            if (sourceView === targetView) {
              return false; // 不能连接到自己
            }

            if (!targetView) {
              return false; // 必须有目标
            }

            return true;
          },
        },
      });
      this.graph.use(new Snapline());
      this.dnd = new Dnd({ target: this.graph });
    },

    initNodes() {
      // 创建节点时为每个节点添加四个方向的连接桩
      this.graph.addNode({
        x: 100,
        y: 100,
        width: 100,
        height: 100,
        label: "Source",
        ports: {
          groups: {
            top: {
              position: "top",
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  fill: "#aaa",
                  stroke: "#666",
                  strokeWidth: 1,
                  visibility: "hidden",
                },
              },
            },
            right: {
              position: "right",
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  fill: "#aaa",
                  stroke: "#666",
                  strokeWidth: 1,
                  visibility: "hidden",
                },
              },
            },
            bottom: {
              position: "bottom",
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  fill: "#aaa",
                  stroke: "#666",
                  strokeWidth: 1,
                  visibility: "hidden",
                },
              },
            },
            left: {
              position: "left",
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  fill: "#aaa",
                  stroke: "#666",
                  strokeWidth: 1,
                  visibility: "hidden",
                },
              },
            },
            // 临时端口组定义
            temp: {
              position: "absolute", // 绝对位置
              attrs: {
                circle: {
                  r: 5,
                  magnet: true,
                  fill: "#52c41a", // 绿色填充
                  stroke: "#fff", // 白色边框
                  strokeWidth: 2,
                  visibility: "visible",
                  cursor: "crosshair",
                },
              },
            },
          },
          items: [
            { id: "top-1", group: "top" },
            { id: "right-1", group: "right" },
            { id: "bottom-1", group: "bottom" },
            { id: "left-1", group: "left" },
          ],
        },
      });

      this.graph.addNode({
        x: 300,
        y: 200,
        width: 100,
        height: 100,
        label: "Target",
        ports: {
          groups: {
            top: {
              position: "top",
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  fill: "#aaa",
                  stroke: "#666",
                  strokeWidth: 1,
                  visibility: "hidden",
                },
              },
            },
            right: {
              position: "right",
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  fill: "#aaa",
                  stroke: "#666",
                  strokeWidth: 1,
                  visibility: "hidden",
                },
              },
            },
            bottom: {
              position: "bottom",
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  fill: "#aaa",
                  stroke: "#666",
                  strokeWidth: 1,
                  visibility: "hidden",
                },
              },
            },
            left: {
              position: "left",
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  fill: "#aaa",
                  stroke: "#666",
                  strokeWidth: 1,
                  visibility: "hidden",
                },
              },
            },
            // 临时端口组定义
            temp: {
              position: "absolute", // 绝对位置
              attrs: {
                circle: {
                  r: 5,
                  magnet: true,
                  fill: "#52c41a", // 绿色填充
                  stroke: "#fff", // 白色边框
                  strokeWidth: 2,
                  visibility: "visible",
                  cursor: "crosshair",
                },
              },
            },
          },
          items: [
            { id: "top-2", group: "top" },
            { id: "right-2", group: "right" },
            { id: "bottom-2", group: "bottom" },
            { id: "left-2", group: "left" },
          ],
        },
      });

      this.graph.addNode({
        x: 250,
        y: 400,
        width: 100,
        height: 100,
        label: "Other",
        ports: {
          groups: {
            top: {
              position: "top",
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  fill: "#aaa",
                  stroke: "#666",
                  strokeWidth: 1,
                  visibility: "hidden",
                },
              },
            },
            right: {
              position: "right",
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  fill: "#aaa",
                  stroke: "#666",
                  strokeWidth: 1,
                  visibility: "hidden",
                },
              },
            },
            bottom: {
              position: "bottom",
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  fill: "#aaa",
                  stroke: "#666",
                  strokeWidth: 1,
                  visibility: "hidden",
                },
              },
            },
            left: {
              position: "left",
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  fill: "#aaa",
                  stroke: "#666",
                  strokeWidth: 1,
                  visibility: "hidden",
                },
              },
            },
            // 临时端口组定义
            temp: {
              position: "absolute", // 绝对位置
              attrs: {
                circle: {
                  r: 5,
                  magnet: true,
                  fill: "#52c41a", // 绿色填充
                  stroke: "#fff", // 白色边框
                  strokeWidth: 2,
                  visibility: "visible",
                  cursor: "crosshair",
                },
              },
            },
          },
          items: [
            { id: "top-2", group: "top" },
            { id: "right-2", group: "right" },
            { id: "bottom-2", group: "bottom" },
            { id: "left-2", group: "left" },
          ],
        },
      });
    },

    initEvents() {
      // 1. 鼠标移入节点显示连接桩
      this.graph.on("node:mouseenter", ({ node }) => {
        // 端点拖拽时不显示连接桩，避免与目标高亮冲突
        if (this.isDraggingEndpoint) {
          return;
        }

        const ports = node.getPorts();
        ports.forEach((port) => {
          try {
            // 过滤掉临时端口，保持其原有样式
            if (this.tempPorts.has(port.id)) {
              return;
            }
            
            node.setPortProp(
              port.id,
              "attrs/circle/style/visibility",
              "visible"
            );
            node.setPortProp(port.id, "attrs/circle/r", 6);
            node.setPortProp(port.id, "attrs/circle/stroke", "#1890ff");
            node.setPortProp(port.id, "attrs/circle/strokeWidth", 2);
            node.setPortProp(port.id, "attrs/circle/fill", "#fff");
            node.setPortProp(port.id, "attrs/circle/cursor", "crosshair");
          } catch (portError) {
            console.warn(`端口 ${port.id} 样式设置失败:`, portError);
          }
        });
      });

      // 鼠标离开节点隐藏连接桩
      this.graph.on("node:mouseleave", ({ node }) => {
        // 端点拖拽时不处理连接桩隐藏，避免与目标高亮冲突
        if (this.isDraggingEndpoint) {
          return;
        }

        const ports = node.getPorts();
        ports.forEach((port) => {
          try {
            // 过滤掉临时端口，保持其原有样式
            if (this.tempPorts.has(port.id)) {
              return;
            }
            
            node.setPortProp(
              port.id,
              "attrs/circle/style/visibility",
              "hidden"
            );
            node.setPortProp(port.id, "attrs/circle/r", 4);
            node.setPortProp(port.id, "attrs/circle/stroke", "#666");
            node.setPortProp(port.id, "attrs/circle/strokeWidth", 1);
            node.setPortProp(port.id, "attrs/circle/fill", "#aaa");
            node.setPortProp(port.id, "attrs/circle/cursor", "default");
          } catch (portError) {
            console.warn(`端口 ${port.id} 隐藏失败:`, portError);
          }
        });
      });

      // 2. 连接桩悬停放大效果
      this.graph.on("cell:mouseover", ({ e }) => {
        if (
          e.target &&
          e.target.getAttribute &&
          e.target.getAttribute("port")
        ) {
          const portId = e.target.getAttribute("port");

          // 端点拖拽时不处理连接桩悬停效果
          if (this.isDraggingEndpoint) {
            return;
          }
          
          // 过滤掉临时端口，保持其原有样式
          if (this.tempPorts.has(portId)) {
            return;
          }
          
          const port = e.target;
          port.setAttribute("r", "8");
          port.setAttribute("stroke-width", "3");
          port.setAttribute("fill", "#1890ff");
          port.setAttribute("stroke", "#fff");
          port.style.cursor = "crosshair";
        }
      });

      // 鼠标移出连接桩样式恢复
      this.graph.on("cell:mouseout", ({ e }) => {
        if (
          e.target &&
          e.target.getAttribute &&
          e.target.getAttribute("port")
        ) {
          const portId = e.target.getAttribute("port");

          // 端点拖拽时不处理连接桩样式恢复
          if (this.isDraggingEndpoint) {
            return;
          }
          
          // 过滤掉临时端口，保持其原有样式
          if (this.tempPorts.has(portId)) {
            return;
          }
          
          const port = e.target;
          port.setAttribute("r", "6");
          port.setAttribute("stroke-width", "2");
          port.setAttribute("fill", "#fff");
          port.setAttribute("stroke", "#1890ff");
          port.style.cursor = "crosshair";
        }
      });

      // 3. 连线悬停效果
      this.graph.on("edge:mouseenter", ({ edge }) => {
        if (!this.dragState.isDragging) {
          edge.attr("line/stroke", "#1890ff");
          edge.attr("line/strokeWidth", 3);
        }
      });

      this.graph.on("edge:mouseleave", ({ edge }) => {
        if (!this.dragState.isDragging) {
          edge.attr("line/stroke", "#666");
          edge.attr("line/strokeWidth", 2);
        }
      });

      // 4. 连接建立事件监听
      this.graph.on("edge:connected", ({ edge, isNew }) => {
        if (isNew && this.dragState.isDragging) {
          const targetPortId = edge.getTargetPortId();
          
          // 检查是否是精准连接创建的连线
          if (this.tempPorts.has(targetPortId)) {
            console.log("✅ [步骤5] 精准连线创建成功");
          } else {
            // 删除意外的默认连接
            setTimeout(() => {
              try {
                this.graph.removeEdge(edge.id);
              } catch (error) {
                console.error("删除意外连接失败:", error);
              }
            }, 0);
          }
        }
      });
      
      // 4.1 连接添加事件监听
      this.graph.on("edge:added", () => {
        // 简化的连接监控，仅用于调试
      });

      // 4.2 拖拽状态重置事件
      this.graph.on("blank:mousedown", () => {
        if (this.dragState.isDragging) {
          this.resetDragState();
        }
      });

      this.graph.on("blank:mouseup", () => {
        if (this.dragState.isDragging) {
          this.resetDragState();
        }
      });

      // 4.3 精准连接触发事件
      this.graph.on("edge:mouseup", (args) => {
        if (this.dragState.isDragging) {
          // 处理精准连接创建
          if (this.currentHoverNode && args.e) {
            this.createPreciseConnection(args.e, this.currentHoverNode);
          }

          setTimeout(() => {
            if (this.dragState.isDragging) {
              this.resetDragState();
            }
          }, 100);
        }
      });

      // 5. 拦截初次连线的实时更新，应用边框吸附
      this.graph.on("edge:change:target", ({ edge, current }) => {
        // 只处理正在拖拽的临时连线
        if (this.dragState.isDragging && this._shouldApplyAttachment && this._pendingAttachmentPoint) {
          const source = edge.getSource();
          const isMatchingEdge = source.cell === this.dragState.sourceNode.id && 
                                 source.port === this.dragState.sourcePort &&
                                 !current.cell; // 确保是浮动目标
          
          if (isMatchingEdge) {
            // 使用我们计算的边框吸附点
            edge.setTarget(this._pendingAttachmentPoint, { silent: true });
            
            // 清除标志，避免重复应用
            this._shouldApplyAttachment = false;
          }
        }
      });

      // 6. 清理临时桩的逻辑
      this.graph.on("edge:removed", ({ edge }) => {
        const targetPortId = edge.getTargetPortId();
        const targetNode = edge.getTargetNode();

        if (targetNode && targetPortId && this.tempPorts.has(targetPortId)) {
          targetNode.removePort(targetPortId);
          this.tempPorts.delete(targetPortId);
        }
      });
    },

    // 重置拖拽状态
    resetDragState() {
      this.dragState.isDragging = false;
      this.dragState.sourceNode = null;
      this.dragState.sourcePort = null;
      this.dragState.tempEdge = null;
      this.dragState.currentTarget = null;

      // 清理边框吸附相关状态
      this._pendingAttachmentPoint = null;
      this._shouldApplyAttachment = false;

      // 清除目标节点高亮
      if (this.currentHoverNode) {
        this.clearTargetNodeHighlight(this.currentHoverNode);
        this.currentHoverNode = null;
      }
    },

    // 设置全局鼠标追踪
    setupGlobalMouseTracking() {
      const container = this.$refs.container;
      if (container) {
        container.addEventListener("mousemove", (e) => {
          // 记录鼠标位置
          this.lastMousePosition = this.getMousePosition(e);
          
          if (this.dragState.isDragging) {
            // 初次连线时添加边框吸附预览效果
            this.updateInitialDragPreview(e);
            
            // 检测目标节点
            const elementUnderMouse = document.elementFromPoint(
              e.clientX,
              e.clientY
            );
            const nodeElement = elementUnderMouse?.closest(".x6-node");

            if (nodeElement) {
              const nodeId = nodeElement.getAttribute("data-cell-id");
              const targetNode = this.graph.getCellById(nodeId);

              if (
                targetNode &&
                targetNode.isNode() &&
                targetNode !== this.dragState.sourceNode
              ) {
                if (
                  !this.currentHoverNode ||
                  this.currentHoverNode.id !== nodeId
                ) {
                  // 清理之前的高亮
                  if (this.currentHoverNode) {
                    this.clearTargetNodeHighlight(this.currentHoverNode);
                  }
                  // 高亮新的目标节点
                  this.highlightTargetNode(targetNode);
                  this.currentHoverNode = targetNode;
                }
              }
            } else if (this.currentHoverNode) {
              // 离开节点时清除高亮
              this.clearTargetNodeHighlight(this.currentHoverNode);
              this.currentHoverNode = null;
            }
          }
        });
      }
    },

    // 初次连线时的边框吸附预览更新
    updateInitialDragPreview(mouseEvent) {
      // 只在有目标节点时处理
      if (!this.currentHoverNode) {
        return;
      }

      try {
        // 计算边框吸附点
        const mousePoint = this.getMousePosition(mouseEvent);
        const attachmentPoint = IntersectionCalculator.calculateBorderAttachmentPoint(
          mousePoint,
          this.currentHoverNode,
          { allowInternalConnection: false } // 固定为禁止内部连接
        );

        // 存储计算结果，供edge:change监听器使用
        this._pendingAttachmentPoint = attachmentPoint;
        this._shouldApplyAttachment = true;

      } catch (error) {
        console.error("❌ 初次连线边框吸附预览计算失败:", error);
      }
    },

    // 高亮目标节点边框
    highlightTargetNode(node) {
      try {
        this.addDOMBorderHighlight(node);
      } catch (error) {
        console.error("❌ 高亮目标节点失败:", error);
      }
    },

    // 添加DOM边框高亮效果
    addDOMBorderHighlight(node) {
      try {
        this.removeDOMBorderHighlight(node);

        const bbox = node.getBBox();
        const container = this.graph.container;
        const borderOverlay = document.createElement("div");
        
        borderOverlay.id = `border-highlight-${node.id}`;
        borderOverlay.style.cssText = `
          position: absolute;
          left: ${bbox.x -3}px;
          top: ${bbox.y -3}px;
          width: ${bbox.width }px;
          height: ${bbox.height }px;
          border: 3px dashed #52c41a;
          border-radius: 4px;
          pointer-events: none;
          z-index: 999;
          box-shadow: 0 0 8px rgba(82, 196, 26, 0.5);
          animation: border-glow 2s infinite;
        `;

        container.appendChild(borderOverlay);

        // 添加CSS动画
        if (!document.getElementById("border-highlight-styles")) {
          const style = document.createElement("style");
          style.id = "border-highlight-styles";
          style.textContent = `
            @keyframes border-glow {
              0% { opacity: 0.8; transform: scale(1); }
              50% { opacity: 1; transform: scale(1.02); }
              100% { opacity: 0.8; transform: scale(1); }
            }
          `;
          document.head.appendChild(style);
        }
      } catch (error) {
        console.error("添加DOM边框高亮失败:", error);
      }
    },

    // 清除目标节点高亮
    clearTargetNodeHighlight(node) {
      try {
        this.removeDOMBorderHighlight(node);
      } catch (error) {
        console.error("清除目标节点高亮失败:", error);
      }
    },

    // 移除DOM边框高亮
    removeDOMBorderHighlight(node) {
      try {
        const borderOverlay = document.getElementById(
          `border-highlight-${node.id}`
        );
        if (borderOverlay && borderOverlay.parentNode) {
          borderOverlay.parentNode.removeChild(borderOverlay);
        }
      } catch (error) {
        console.error("移除DOM边框高亮失败:", error);
      }
    },

    // ===================== 线条类型选择器 =====================

    // 初始化线条类型选择器
    initLineTypeSelector() {
      // 设置默认选中第一个线条类型
      this.selectedLineType = this.lineTypes[0];
      console.log(
        "✅ 线条类型选择器初始化完成，默认选中:",
        this.selectedLineType.name
      );
    },

    // 选择线条类型
    selectLineType(lineType) {
      this.selectedLineType = lineType;
      console.log("🎨 切换线条类型:", lineType.name);
    },

    // 获取当前选中的线条样式配置
    getCurrentLineStyle() {
      if (!this.selectedLineType) {
        // 回退到默认样式
        return {
          style: {
            stroke: "#666",
            strokeWidth: 2,
          },
          targetMarker: {
            name: "block",
            width: 12,
            height: 8,
          },
          router: "normal",
          connector: "normal",
        };
      }
      
      return {
        style: this.selectedLineType.style,
        targetMarker: this.selectedLineType.targetMarker,
        sourceMarker: this.selectedLineType.sourceMarker,
        router: this.selectedLineType.router,
        connector: this.selectedLineType.connector,
      };
    },

    // ===================== 步骤6: 连线重连功能 =====================

    // 阶段1: 连线选中与端点显示
    initEdgeSelectionEvents() {
      // 监听连线点击事件
      this.graph.on("edge:click", ({ edge, e }) => {
        this.clearEdgeSelection();
        this.selectEdge(edge);
        this.showEndpointControllers(edge);
        e.stopPropagation();
      });
      
      // 监听空白区域点击，清除选中
      this.graph.on("blank:click", () => {
        if (this.selectedEdge) {
          this.clearEdgeSelection();
        }
      });
      
      // 监听节点点击，清除连线选中（避免冲突）
      this.graph.on("node:click", () => {
        if (this.selectedEdge) {
          this.clearEdgeSelection();
        }
      });

      // 监听节点移动过程（实时跟随）
      this.graph.on("node:moving", () => {
        if (this.selectedEdge && this.edgeEndpoints.length > 0) {
          // 使用requestAnimationFrame优化性能
          if (!this._updateScheduled) {
            this._updateScheduled = true;
            requestAnimationFrame(() => {
              this.updateEndpointControllers(true); // 实时更新，不打印日志
              this._updateScheduled = false;
            });
          }
        }
      });

      // 监听节点移动结束（确保最终位置正确）
      this.graph.on("node:moved", () => {
        if (this.selectedEdge && this.edgeEndpoints.length > 0) {
          this.updateEndpointControllers(false);
        }
      });

      // 监听连线变化，更新端点控制器位置
      this.graph.on("edge:change:source", ({ edge }) => {
        if (this.selectedEdge && edge.id === this.selectedEdge.id) {
          this.updateEndpointControllers();
        }
      });

      this.graph.on("edge:change:target", ({ edge }) => {
        if (this.selectedEdge && edge.id === this.selectedEdge.id) {
          this.updateEndpointControllers();
        }
      });
    },

    // 选中连线
    selectEdge(edge) {
      this.selectedEdge = edge;
      edge.attr("line/stroke", "#1890ff");
      edge.attr("line/strokeWidth", 3);
      edge.setZIndex(1000);
    },

    // 清除连线选中状态
    clearEdgeSelection() {
      if (this.selectedEdge) {
        this.selectedEdge.attr("line/stroke", "#666");
        this.selectedEdge.attr("line/strokeWidth", 2);
        this.selectedEdge.attr("line/strokeDasharray", "");
        this.selectedEdge.setZIndex(0);
        this.selectedEdge = null;
      }
      this.clearEndpointControllers();
    },

    // 显示端点控制器
    showEndpointControllers(edge) {
      try {
        const sourcePoint = edge.getSourcePoint();
        const targetPoint = edge.getTargetPoint();
        this.createEndpointController("source", sourcePoint, edge);
        this.createEndpointController("target", targetPoint, edge);
      } catch (error) {
        console.error("❌ 显示端点控制器失败:", error);
      }
    },

    // 创建端点控制器
    createEndpointController(type, point, edge) {
      try {
        // 创建DOM端点控制器元素
        const controller = document.createElement("div");
        controller.className = `endpoint-controller endpoint-${type}`;
        controller.style.cssText = `
          position: absolute;
          left: 0;
          top: 0;
          transform: translate3d(${point.x - 8}px, ${point.y - 8}px, 0);
          width: 16px;
          height: 16px;
          background: #1890ff;
          border: 2px solid #fff;
          border-radius: 50%;
          cursor: grab;
          z-index: 1001;
          box-shadow: 0 2px 4px rgba(0,0,0,0.2);
          transition: none;
          will-change: transform;
        `;
        
        // 保存控制器的当前位置获取函数
        controller._getPosition = () => {
          if (!this.selectedEdge) return { x: point.x, y: point.y };
          const currentPoint =
            type === "source"
            ? this.selectedEdge.getSourcePoint() 
            : this.selectedEdge.getTargetPoint();
          return currentPoint;
        };

        // 悬停效果
        controller.addEventListener("mouseenter", () => {
          // 临时启用过渡动画用于悬停效果
          controller.style.transition = "transform 0.15s ease-out";
          const pos = controller._getPosition();
          controller.style.transform = `translate3d(${pos.x - 8}px, ${
            pos.y - 8
          }px, 0) scale(1.2)`;
        });
        
        controller.addEventListener("mouseleave", () => {
          if (!this.isDraggingEndpoint) {
            // 临时启用过渡动画用于悬停效果
            controller.style.transition = "transform 0.15s ease-out";
            const pos = controller._getPosition();
            controller.style.transform = `translate3d(${pos.x - 8}px, ${
              pos.y - 8
            }px, 0) scale(1)`;
            
            // 延迟移除过渡动画，确保悬停动画完成
            setTimeout(() => {
              controller.style.transition = "none";
            }, 150);
          }
        });
        
        // 添加拖拽事件（阶段2实现）
        this.addEndpointDragEvents(controller, type, edge);
        
        // 添加到画布容器
        this.graph.container.appendChild(controller);
        
        // 记录端点控制器
        this.edgeEndpoints.push({ 
          element: controller, 
          type, 
          edge,
          id: `${edge.id}-${type}`,
        });
      } catch (error) {
        console.error(`❌ 创建${type}端点控制器失败:`, error);
      }
    },

    // 清理端点控制器
    clearEndpointControllers() {
      this.edgeEndpoints.forEach(({ element }) => {
        try {
          if (element && element.parentNode) {
            element.parentNode.removeChild(element);
          }
        } catch (error) {
          console.error("清理端点控制器失败:", error);
        }
      });
      this.edgeEndpoints = [];
    },

    // 更新端点控制器位置
    updateEndpointControllers() {
      if (!this.selectedEdge || this.edgeEndpoints.length === 0) {
        return;
      }

      try {
        // 获取连线的当前端点位置
        const sourcePoint = this.selectedEdge.getSourcePoint();
        const targetPoint = this.selectedEdge.getTargetPoint();

        // 更新每个端点控制器的位置
        this.edgeEndpoints.forEach(({ element, type }) => {
          const point = type === "source" ? sourcePoint : targetPoint;
          
          // 使用translate3d启用GPU加速，性能更好
          element.style.transform = `translate3d(${point.x - 8}px, ${
            point.y - 8
          }px, 0)`;
        });
      } catch (error) {
        console.error("❌ 更新端点控制器位置失败:", error);
      }
    },

    // ===================== 阶段2: 端点拖拽功能 =====================

    // 阶段2.1: 添加端点拖拽事件
    addEndpointDragEvents(controller, type, edge) {
      try {
        let isDragging = false;

        // 鼠标按下开始拖拽
        const handleMouseDown = (e) => {
          isDragging = true;
          this.isDraggingEndpoint = true;

          // 保存拖拽开始时的原始状态
          this.draggedEndpoint = {
            type,
            edge,
            controller,
            originalSourcePort: edge.getSourcePortId(),
            originalTargetPort: edge.getTargetPortId(),
            originalSourceNode: edge.getSourceNode().id,
            originalTargetNode: edge.getTargetNode().id,
          };


          // 创建拖拽预览线
          this.createDragPreviewLine(edge, type);

          // 设置拖拽样式：隐藏被拖拽的端点控制器
          controller.style.cursor = "grabbing";
          controller.style.opacity = "0"; // 隐藏原端点

          // 设置画布鼠标指针为十字形，与步骤4保持一致
          const container = this.graph.container;
          container.style.cursor = "crosshair";

          // 阻止事件冒泡，避免触发连线选中
          e.stopPropagation();
          e.preventDefault();
        };

        // 全局鼠标移动处理
        const handleMouseMove = (e) => {
          if (!isDragging || this.draggedEndpoint?.controller !== controller)
            return;

          // 使用requestAnimationFrame节流优化性能
          if (!this._dragUpdateScheduled) {
            this._dragUpdateScheduled = true;
            requestAnimationFrame(() => {
              this.updateDragPreview(e);
              this._dragUpdateScheduled = false;
            });
          }
        };

        // 全局鼠标释放处理
        const handleMouseUp = (e) => {
          if (!isDragging) return;

          isDragging = false;
          this.isDraggingEndpoint = false;

          // 处理端点重连逻辑（阶段3实现）
          this.handleEndpointReconnection(e);

          // 清理拖拽状态
          this.cleanupDragState();
        };

        // 绑定事件
        controller.addEventListener("mousedown", handleMouseDown);
        document.addEventListener("mousemove", handleMouseMove);
        document.addEventListener("mouseup", handleMouseUp);

        // 保存事件处理器引用，用于清理
        controller._dragEventHandlers = {
          mousedown: handleMouseDown,
          mousemove: handleMouseMove,
          mouseup: handleMouseUp,
        };
      } catch (error) {
        console.error(`❌ [阶段2.1] 添加${type}端点拖拽事件失败:`, error);
      }
    },

    // 阶段2.1: 创建拖拽预览线
    createDragPreviewLine(originalEdge, dragType) {
      try {
        // 获取原连线的样式配置
        const lineConfig = this.getCurrentLineStyle();

        // 获取连线当前端点
        const sourcePoint = originalEdge.getSourcePoint();
        const targetPoint = originalEdge.getTargetPoint();

        // 创建预览线，初始位置与原连线相同
        this.dragPreviewLine = this.graph.addEdge({
          source: { x: sourcePoint.x, y: sourcePoint.y },
          target: { x: targetPoint.x, y: targetPoint.y },
          router: lineConfig.router,
          connector: lineConfig.connector,
          attrs: {
            line: {
              // 使用与步骤4相同的样式（灰色实线）
              stroke: "#666", // 灰色，与步骤4一致
              strokeWidth: 2,
              opacity: 0.8,
              // 关键修复：禁用鼠标事件，避免遮挡检测（复用步骤4方案）
              pointerEvents: "none",
            },
          },
          zIndex: 1000,
        });

        // 在预览线的拖拽端添加端点样式标记
        this.addPreviewLineEndpoint(dragType);

        // 设置原连线为半透明
        originalEdge.attr("line/opacity", 0.3);
      } catch (error) {
        console.error("❌ [阶段2.1] 创建拖拽预览线失败:", error);
      }
    },

    // 阶段2.2: 增强预览线跟随功能
    updateDragPreview(mouseEvent) {
      if (!this.dragPreviewLine || !this.draggedEndpoint) return;

      try {
        // 获取鼠标位置
        const mousePoint = PositionCalculator.getMousePosition(
          mouseEvent,
          this.graph.container
        );

        // 检查鼠标是否在画布范围内
        const container = this.graph.container;
        const containerRect = container.getBoundingClientRect();
        const isInsideCanvas =
          mousePoint.x >= 0 &&
          mousePoint.x <= containerRect.width &&
          mousePoint.y >= 0 &&
          mousePoint.y <= containerRect.height;

        // 优先使用边界吸附，其次使用智能偏移
        let targetPoint;
        
        if (this.currentHoverNode) {
          // 有目标节点时：使用边界吸附
          targetPoint = IntersectionCalculator.calculateBorderAttachmentPoint(
            mousePoint,
            this.currentHoverNode,
            { allowInternalConnection: false } // 固定为禁止内部连接
          );
        } else {
          // 无目标节点时：使用智能偏移
          const offset = this.calculateSmartOffset(mousePoint);
          targetPoint = {
            x: mousePoint.x + offset.x,
            y: mousePoint.y + offset.y,
          };
        }

        // 根据拖拽的端点类型更新预览线
        if (this.draggedEndpoint.type === "source") {
          this.dragPreviewLine.setSource(targetPoint);
        } else {
          this.dragPreviewLine.setTarget(targetPoint);
        }

        // 根据位置调整预览线样式
        if (isInsideCanvas) {
          this.dragPreviewLine.attr("line/opacity", 0.8);
          this.dragPreviewLine.attr("line/stroke", "#666");
        } else {
          this.dragPreviewLine.attr("line/opacity", 0.5);
          this.dragPreviewLine.attr("line/stroke", "#ff4d4f");
        }

        // 更新预览线端点标记位置
        this.updatePreviewLineEndpoint();

        // 使用增强的实时目标检测
        this.detectTargetNodeForEndpoint_RealTime_Enhanced();
      } catch (error) {
        console.error("❌ [阶段2.2] 更新拖拽预览失败:", error);
      }
    },

    // 阶段2.2: 在预览线端点添加端点样式（视觉欺骗方案）
    addPreviewLineEndpoint(dragType) {
      try {
        // 获取预览线当前的拖拽端点位置
        const point =
          dragType === "source"
            ? this.dragPreviewLine.getSourcePoint()
            : this.dragPreviewLine.getTargetPoint();

        // 创建跟随预览线的端点标记
        const endpointMarker = document.createElement("div");
        endpointMarker.className = `preview-endpoint preview-${dragType}`;
        endpointMarker.style.cssText = `
          position: absolute;
          left: 0;
          top: 0;
          transform: translate3d(${point.x - 8}px, ${point.y - 8}px, 0);
          width: 16px;
          height: 16px;
          background: #1890ff;
          border: 2px solid #fff;
          border-radius: 50%;
          cursor: grabbing;
          z-index: 1002;
          box-shadow: 0 4px 8px rgba(24, 144, 255, 0.4);
          pointer-events: none;
          will-change: transform;
        `;

        // 添加到画布容器
        this.graph.container.appendChild(endpointMarker);

        // 保存引用用于后续更新和清理
        this.previewEndpointMarker = endpointMarker;
      } catch (error) {
        console.error("❌ [阶段2.2] 创建预览线端点失败:", error);
      }
    },

    // 阶段2.2: 更新预览线端点标记位置
    updatePreviewLineEndpoint() {
      if (
        !this.previewEndpointMarker ||
        !this.dragPreviewLine ||
        !this.draggedEndpoint
      )
        return;

      try {
        // 获取预览线当前的拖拽端点位置
        const point =
          this.draggedEndpoint.type === "source"
            ? this.dragPreviewLine.getSourcePoint()
            : this.dragPreviewLine.getTargetPoint();

        // 更新端点标记位置（与预览线完全同步）
        this.previewEndpointMarker.style.transform = `translate3d(${
          point.x - 8
        }px, ${point.y - 8}px, 0)`;
      } catch (error) {
        console.error("❌ [阶段2.2] 更新预览线端点位置失败:", error);
      }
    },

    // 智能偏移计算：根据拖拽方向避开鼠标指针
    calculateSmartOffset(currentMousePoint) {
      try {

        if (!this.draggedEndpoint || !this.dragPreviewLine) {
          return { x: 10, y: 10 };
        }

        const fixedPoint = this.draggedEndpoint.type === "source"
          ? this.dragPreviewLine.getTargetPoint()
          : this.dragPreviewLine.getSourcePoint();

        const direction = {
          x: currentMousePoint.x - fixedPoint.x,
          y: currentMousePoint.y - fixedPoint.y,
        };

        const length = Math.sqrt(direction.x * direction.x + direction.y * direction.y);
        if (length === 0) {
          return { x: 10, y: 10 };
        }

        const normalizedDirection = {
          x: direction.x / length,
          y: direction.y / length,
        };

        let offset = { x: 0, y: 0 };
        const absX = Math.abs(normalizedDirection.x);
        const absY = Math.abs(normalizedDirection.y);

        if (absX > absY) {
          offset.y = normalizedDirection.x > 0 ? -15 : 15;
        } else {
          offset.x = normalizedDirection.y > 0 ? -15 : 15;
        }

        if (absX > 0.5 && absY > 0.5) {
          offset.x = normalizedDirection.x > 0 ? -10 : 10;
          offset.y = normalizedDirection.y > 0 ? -10 : 10;
        }

        return offset;
      } catch (error) {
        console.error("❌ 智能偏移计算失败:", error);
        return { x: 10, y: 10 };
      }
    },



    // 增强的多点目标棅测，解决偏移算法导致的检测盲区
    detectTargetNodeForEndpoint_RealTime_Enhanced() {
      if (!this.isDraggingEndpoint) return;

      try {
        const baseX = this.lastMousePosition.x + this.graph.container.getBoundingClientRect().left;
        const baseY = this.lastMousePosition.y + this.graph.container.getBoundingClientRect().top;
        
        // 多点检测策略，扩大30px检测范围
        const tolerance = 30;
        const detectionPoints = [
          { x: baseX, y: baseY, priority: 1 },
          { x: baseX - tolerance, y: baseY, priority: 2 },
          { x: baseX + tolerance, y: baseY, priority: 2 },
          { x: baseX, y: baseY - tolerance, priority: 2 },
          { x: baseX, y: baseY + tolerance, priority: 2 },
          { x: baseX - tolerance*0.7, y: baseY - tolerance*0.7, priority: 3 },
          { x: baseX + tolerance*0.7, y: baseY - tolerance*0.7, priority: 3 },
          { x: baseX - tolerance*0.7, y: baseY + tolerance*0.7, priority: 3 },
          { x: baseX + tolerance*0.7, y: baseY + tolerance*0.7, priority: 3 },
        ];

        let bestTarget = null;
        let bestPriority = 999;

        for (const point of detectionPoints) {
          let elementUnderMouse = null;
          
          if (this.dragPreviewLine && this.previewEndpointMarker) {
            const originalLineVisibility = this.dragPreviewLine.attr("line/visibility");
            const originalMarkerDisplay = this.previewEndpointMarker.style.display;
            
            this.dragPreviewLine.attr("line/visibility", "hidden");
            this.previewEndpointMarker.style.display = "none";
            
            elementUnderMouse = document.elementFromPoint(point.x, point.y);
            
            this.dragPreviewLine.attr("line/visibility", originalLineVisibility || "visible");
            this.previewEndpointMarker.style.display = originalMarkerDisplay || "block";
          } else {
            elementUnderMouse = document.elementFromPoint(point.x, point.y);
          }

          const nodeElement = elementUnderMouse?.closest(".x6-node");
          
          if (nodeElement && point.priority < bestPriority) {
            const nodeId = nodeElement.getAttribute("data-cell-id");
            const targetNode = this.graph.getCellById(nodeId);
            
            if (this.isValidTargetForEndpoint(targetNode)) {
              bestTarget = targetNode;
              bestPriority = point.priority;
              
              if (point.priority === 1) break;
            }
          }
        }

        this.processTargetNodeForEndpoint(bestTarget);
        
      } catch (error) {
        console.error("❌ 增强目标检测失败:", error);
        
        if (this.dragPreviewLine) {
          this.dragPreviewLine.attr("line/visibility", "visible");
        }
        if (this.previewEndpointMarker) {
          this.previewEndpointMarker.style.display = "block";
        }
      }
    },

    // 验证目标节点是否有效
    isValidTargetForEndpoint(targetNode) {
      if (!targetNode || !targetNode.isNode()) return false;
      
      const currentSourceNodeId = this.draggedEndpoint.type === "source"
        ? this.draggedEndpoint.edge.getTargetNode().id
        : this.draggedEndpoint.edge.getSourceNode().id;
        
      return targetNode.id !== currentSourceNodeId;
    },

    // 处理目标节点高亮和预览线样式
    processTargetNodeForEndpoint(targetNode) {
      if (targetNode) {
        if (this.currentHoverNode?.id !== targetNode.id) {
          if (this.currentHoverNode) {
            this.clearTargetNodeHighlight(this.currentHoverNode);
          }
          this.highlightTargetNode(targetNode);
          this.currentHoverNode = targetNode;
        }
        
        if (this.dragPreviewLine) {
          this.dragPreviewLine.attr("line/stroke", "#666");
          this.dragPreviewLine.attr("line/opacity", 1.0);
        }
      } else {
        if (this.currentHoverNode) {
          this.clearTargetNodeHighlight(this.currentHoverNode);
          this.currentHoverNode = null;
          
          if (this.dragPreviewLine) {
            this.dragPreviewLine.attr("line/stroke", "#666");
            this.dragPreviewLine.attr("line/opacity", 0.8);
          }
        }
      }
    },

    // 移除冗余的基础检测方法，只保留增强版本

    // 阶段3: 处理端点重连（精准连接集成）
    handleEndpointReconnection(mouseEvent) {
      try {
        const { type, edge, controller } = this.draggedEndpoint;

        if (this.currentHoverNode) {
          // 有目标节点，使用精准连线逻辑创建新连接
          this.createPreciseEndpointConnection(
            mouseEvent,
            this.currentHoverNode,
            type,
            edge
          );
        } else {
          // 没有目标节点，恢复原位置
          this.restoreEndpointPosition(controller, edge, type);
        }
      } catch (error) {
        console.error("❌ [阶段3] 端点重连失败:", error);
        // 出错时也恢复原位置
        this.restoreEndpointPosition(
          this.draggedEndpoint.controller,
          this.draggedEndpoint.edge,
          this.draggedEndpoint.type
        );
      }
    },

    // 阶段3: 创建精准端点连接
    createPreciseEndpointConnection(
      mouseEvent,
      targetNode,
      endpointType,
      originalEdge
    ) {
      try {
        // 1. 计算连接点（专门为端点重连优化的方法）
        const intersectionPoint = this.calculateEndpointReconnectionPoint(
          mouseEvent,
          targetNode
        );

        if (!intersectionPoint) {
          console.error("❌ [阶段3] 无法计算连接点");
          return;
        }

        // 2. 创建临时端口
        const tempPortId = this.createTempPort(targetNode, intersectionPoint);

        if (!tempPortId) {
          console.error("❌ [阶段3] 创建临时端口失败");
          return;
        }

        // 3. 更新原连线的连接
        this.updateEdgeConnection(
          originalEdge,
          endpointType,
          targetNode,
          tempPortId
        );

        // 4. 清理旧的临时端口（如果需要）
        this.cleanupOldTempPort(originalEdge, endpointType);

        // 5. 恢复连线透明度
        originalEdge.attr("line/opacity", 1);

        console.log("✅ [阶段3] 端点重连成功");
      } catch (error) {
        console.error("❌ [阶段3] 创建精准端点连接失败:", error);
        throw error;
      }
    },

    // 阶段3: 更新连线连接
    updateEdgeConnection(edge, endpointType, targetNode, newPortId) {
      try {
        if (endpointType === "source") {
          edge.setSource({
            cell: targetNode.id,
            port: newPortId,
          });
        } else {
          edge.setTarget({
            cell: targetNode.id,
            port: newPortId,
          });
        }

        // 强制更新连线位置
        edge.toFront();
      } catch (error) {
        console.error("❌ [阶段3] 更新连线连接失败:", error);
        throw error;
      }
    },

    // 阶段3: 清理旧的临时端口
    cleanupOldTempPort(edge, endpointType) {
      try {
        // 获取旧的端口信息（从拖拽开始时的状态）
        const oldPortId =
          endpointType === "source"
            ? this.draggedEndpoint.originalSourcePort
            : this.draggedEndpoint.originalTargetPort;

        const oldNodeId =
          endpointType === "source"
            ? this.draggedEndpoint.originalSourceNode
            : this.draggedEndpoint.originalTargetNode;

        if (!oldPortId || !oldNodeId) {
          return; // 没有旧的端口信息
        }

        // 检查是否是临时端口
        if (this.tempPorts.has(oldPortId)) {
          const oldNode = this.graph.getCellById(oldNodeId);

          if (oldNode) {
            // 检查是否还有其他连线使用这个临时端口
            const connectedEdges = this.graph
              .getConnectedEdges(oldNode)
              .filter(
                (e) =>
                  (e.getSourcePortId() === oldPortId ||
                    e.getTargetPortId() === oldPortId) &&
                  e.id !== edge.id
              );

            if (connectedEdges.length === 0) {
              // 没有其他连线使用，可以安全删除
              this.removeTempPort(oldNode, oldPortId);
              console.log("🗑️ [阶段3] 清理无用的临时端口:", oldPortId);
            } else {
              console.log(
                "🔒 [阶段3] 临时端口仍被其他连线使用，保留:",
                oldPortId
              );
            }
          }
        }
      } catch (error) {
        console.error("❌ [阶段3] 清理旧临时端口失败:", error);
      }
    },

    // 阶段3: 计算端点重连的连接点（专门优化版本）
    calculateEndpointReconnectionPoint(mouseEvent, targetNode) {
      try {
        // 获取鼠标位置
        let mousePoint;
        if (mouseEvent && mouseEvent.clientX !== undefined) {
          mousePoint = this.getMousePosition(mouseEvent);
        } else {
          mousePoint = this.lastMousePosition;
        }

        // 使用边框吸附算法
        const result = IntersectionCalculator.calculateBorderAttachmentPoint(
          mousePoint,
          targetNode,
          { allowInternalConnection: false } // 固定为禁止内部连接
        );
        return result;
      } catch (error) {
        console.error("❌ [阶段3] 端点重连连接点计算失败:", error);
        // 返回一个安全的默认位置
        const bbox = targetNode.getBBox();
        return {
          x: bbox.x + bbox.width / 2,
          y: bbox.y + bbox.height / 2,
          edge: "bottom",
          method: "fallback",
        };
      }
    },

    // 阶段3: 恢复端点位置（无目标节点时）
    restoreEndpointPosition(controller, edge, endpointType) {
      try {
        // 获取原连线的端点位置
        const originalPoint =
          endpointType === "source"
            ? edge.getSourcePoint()
            : edge.getTargetPoint();

        // 恢复端点控制器位置
        if (controller && controller.style) {
          controller.style.transform = `translate3d(${originalPoint.x - 8}px, ${
            originalPoint.y - 8
          }px, 0)`;
        }

        // 恢复连线透明度
        edge.attr("line/opacity", 1);

        console.log("🔄 [阶段3] 端点位置已恢复");
      } catch (error) {
        console.error("❌ [阶段3] 恢复端点位置失败:", error);
      }
    },

    // 阶段2: 清理拖拽状态（完整版）
    cleanupDragState() {
      try {
        // 清理预览线
        if (this.dragPreviewLine) {
          this.graph.removeEdge(this.dragPreviewLine.id);
          this.dragPreviewLine = null;
        }

        // 清理预览线端点标记
        if (this.previewEndpointMarker) {
          if (this.previewEndpointMarker.parentNode) {
            this.previewEndpointMarker.parentNode.removeChild(
              this.previewEndpointMarker
            );
          }
          this.previewEndpointMarker = null;
        }

        // 恢复原连线样式
        if (this.selectedEdge) {
          this.selectedEdge.attr("line/opacity", 1);
        }

        // 阶段2.3: 清理目标节点高亮
        if (this.currentHoverNode) {
          this.clearTargetNodeHighlight(this.currentHoverNode);
          this.currentHoverNode = null;
        }

        // 重置拖拽状态
        this.isDraggingEndpoint = false;
        this.draggedEndpoint = null;
        this._dragUpdateScheduled = false;

        // 恢复端点控制器样式
        this.edgeEndpoints.forEach(({ element }) => {
          element.style.cursor = "grab";
          element.style.boxShadow = "0 2px 4px rgba(0,0,0,0.2)"; // 恢复原始阴影
          element.style.opacity = "1"; // 恢复透明度，显示原端点

          // 移除拖拽时的特殊样式，恢复到正常位置
          if (element._getPosition) {
            const pos = element._getPosition();
            element.style.transform = `translate3d(${pos.x - 8}px, ${
              pos.y - 8
            }px, 0) scale(1)`;
          }
        });

        // 恢复画布默认鼠标指针
        const container = this.graph.container;
        container.style.cursor = "default";
      } catch (error) {
        console.error("❌ [阶段2] 清理拖拽状态失败:", error);
      }
    },

    // 计算连线与目标节点边框的相交位置
    calculateLineIntersectionPoint(sourcePoint, mousePoint, targetNode) {
      return IntersectionCalculator.calculateLineIntersectionPoint(
        sourcePoint,
        mousePoint,
        targetNode
      );
    },

    // 获取源连接桩的位置
    getSourcePortPosition(sourceNode, sourcePortId) {
      return PositionCalculator.getSourcePortPosition(sourceNode, sourcePortId);
    },

    // 获取鼠标在画布中的坐标
    getMousePosition(mouseEvent) {
      return PositionCalculator.getMousePosition(
        mouseEvent,
        this.graph.container
      );
    },

    // 创建临时端口
    createTempPort(targetNode, intersectionPoint) {
      try {
        const tempPortId = `temp-port-${Date.now()}-${Math.random()
          .toString(36)
          .substr(2, 9)}`;
        const bbox = targetNode.getBBox();
        
        // 计算相对坐标
        const relativeX = intersectionPoint.x - bbox.x;
        const relativeY = intersectionPoint.y - bbox.y;

        // 添加临时端口到目标节点（默认隐藏）
        targetNode.addPort({
          id: tempPortId,
          group: "temp",
          args: { x: relativeX, y: relativeY },
          attrs: {
            circle: {
              r: 5,
              magnet: true,
              fill: "#52c41a",
              stroke: "#fff",
              strokeWidth: 2,
              visibility: "hidden", // 默认隐藏
              cursor: "crosshair",
            },
          },
        });

        this.tempPorts.add(tempPortId);

        return tempPortId;
      } catch (error) {
        console.error("❌ [阶段2失败] 创建临时端口失败:", error);
        return null;
      }
    },

    // 清理临时端口
    removeTempPort(targetNode, tempPortId) {
      try {
        if (targetNode && tempPortId && this.tempPorts.has(tempPortId)) {
          targetNode.removePort(tempPortId);
          this.tempPorts.delete(tempPortId);
        }
      } catch (error) {
        console.error("清理临时端口失败:", error);
      }
    },

    // 计算精准连接位置
    calculateConnectionPoint(mouseEvent, targetNode) {
      try {
        // 保护检查：确保这是步骤5的调用，不是步骤6的端点重连
        if (this.isDraggingEndpoint) {
          return null;
        }

        // 获取鼠标位置
        let mousePoint;
        if (mouseEvent && mouseEvent.clientX !== undefined) {
          mousePoint = this.getMousePosition(mouseEvent);
        } else {
          mousePoint = this.lastMousePosition;
        }
        
        // 使用边框吸附算法
        const result = IntersectionCalculator.calculateBorderAttachmentPoint(
          mousePoint,
          targetNode,
          { allowInternalConnection: false } // 固定为禁止内部连接
        );
        return result;
      } catch (error) {
        console.error("❌ [阶段1失败] 连接位置计算失败:", error);
        const bbox = targetNode.getBBox();
        return {
          x: bbox.x,
          y: bbox.y + bbox.height / 2,
          edge: "left",
          method: "error",
        };
      }
    },

    // 完整的精准连接创建流程
    createPreciseConnection(mouseEvent, targetNode) {
      try {
        // 检查前置条件
        if (!this.dragState.sourceNode || !this.dragState.sourcePort) {
          console.error("❌ 拖拽状态不完整，无法创建精准连接");
          return false;
        }
        
        // 计算精准位置
        const intersectionPoint = this.calculateConnectionPoint(
          mouseEvent,
          targetNode
        );
        if (!intersectionPoint) {
          console.error("❌ 无法计算交点位置");
          return false;
        }
        
        // 创建临时端口
        const tempPortId = this.createTempPort(targetNode, intersectionPoint);
        if (!tempPortId) {
          console.error("❌ 无法创建临时端口");
          return false;
        }
        
        // 保存拖拽状态信息
        const sourceNodeId = this.dragState.sourceNode.id;
        const sourcePortId = this.dragState.sourcePort;
        
        // 延迟创建连线，确保临时端口渲染完成
        setTimeout(() => {
          // 确认临时端口存在
          const portExists = targetNode.getPort(tempPortId);
          if (!portExists) {
            console.error("❌ 临时端口不存在，无法创建连线");
            return;
          }
          
          // 创建连线，应用选中的线条类型样式
          const lineConfig = this.getCurrentLineStyle();
          const edge = this.graph.addEdge({
            source: { cell: sourceNodeId, port: sourcePortId },
            target: { cell: targetNode.id, port: tempPortId },
            router: lineConfig.router,
            connector: lineConfig.connector,
            attrs: {
              line: {
                ...lineConfig.style,
                targetMarker: lineConfig.targetMarker,
                sourceMarker: lineConfig.sourceMarker,
              },
            },
          });
          
          // 优化连线渲染
          this.$nextTick(() => {
            try {
              edge.toFront();
            } catch (error) {
              console.warn("连线置前失败:", error);
            }
          });
        }, 80); // 关键：使用80ms延迟解决X6渲染时序问题
        
        // 重置拖拽状态
        this.resetDragState();
        
        return { tempPortId, intersectionPoint };
      } catch (error) {
        console.error("❌ 创建精准连接失败:", error);
        this.resetDragState();
        return false;
      }
    },

  },
  beforeDestroy() {
    // 清理可能残留的DOM边框高亮
    if (this.currentHoverNode) {
      this.removeDOMBorderHighlight(this.currentHoverNode);
    }
    
    // 清理连线选中状态和端点控制器
    this.clearEdgeSelection();

    // 清理图形实例
    if (this.graph) {
      this.graph.dispose();
    }
  },
};
</script>

<style scoped>
.x6-connector-wrapper {
  position: relative;
  width: 100%;
  height: 600px;
}

.x6-container {
  width: 100%;
  height: 100%;
  border: 1px solid #eee;
  position: relative;
}

/* 线条类型选择器样式 */
.line-type-selector {
  position: absolute;
  top: 10px;
  left: 10px;
  background: white;
  border-radius: 6px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  overflow: hidden;
  z-index: 1000;
  border: 1px solid #e8e8e8;
}

.line-type-tabs {
  display: flex;
}

.line-type-tab {
  padding: 6px 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  cursor: pointer;
  border-right: 1px solid #f0f0f0;
  transition: all 0.3s;
  min-width: 65px;
  background: white;
}

.line-type-tab:last-child {
  border-right: none;
}

.line-type-tab:hover {
  background: #f8f9fa;
}

.line-type-tab.active {
  background: #1890ff;
  color: white;
}

.line-type-tab.active:hover {
  background: #40a9ff;
}

.line-type-icon {
  font-size: 16px;
  font-weight: bold;
  line-height: 1;
}

.line-type-name {
  font-size: 11px;
  text-align: center;
  white-space: nowrap;
}

</style>